/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#include "module.h"
#include "arch.h"
#include "../common/debug.h"

namespace sleepyface
{
    namespace arch
    {
        ModuleValue::ModuleValue()
        {
            type = _uninitialized;
            b = false;
            i = 0;
            s = "";
            d = NULL;
        }

        ModuleValue::ModuleValue(int t, int v)
        {
            ModuleValue();

            type = t;

            if (t == _bool)
                b = (v > 0);
            else if (t == _int)
                i = v;
            else if (t == _string)
            {
                stringstream ss;
                ss << (int)v;
                s = ss.str();
            }
            else if (t == _data)
                d = new int(v);
            else
                t = _uninitialized;
        }

        ModuleValue::ModuleValue(int t, string v)
        {
            ModuleValue();

            type = t;

            if (t == _bool)
                b = !v.empty();
            else if (t == _int)
                i = atoi(v.c_str());
            else if (t == _string)
                s = v;
            else if (t == _data)
                d = new string(v);
            else
                t = _uninitialized;
        }

        ModuleValue::ModuleValue(int t, void *v)
        {
            ModuleValue();

            type = t;

            if (t == _bool)
                b = v != NULL;
            else if (t == _int)
                i = (int)v;
            else if (t == _string)
            {
                stringstream ss;
                ss << (void *)v;
                s = ss.str();
            }
            else if (t == _data)
                d = v;
            else
                t = _uninitialized;
        }

        int ModuleValue::getType()
        {
            return type;
        }

        bool ModuleValue::getBool()
        {
            if (type == _uninitialized)
                return false;
            else if (type == _bool)
                return b;
            else if (type == _int)
                return i > 0;
            else if (type == _string)
                return !s.empty();
            else if (type == _data)
                return d != NULL;
            else
                return false;
        }

        int ModuleValue::getInt()
        {
            if (type == _uninitialized)
                return 0;
            else if (type == _bool)
                return (int)b;
            else if (type == _int)
                return i;
            else if (type == _string)
                return atoi(s.c_str());
            else if (type == _data)
                return (int)d;
            else
                return 0;
        }

        string ModuleValue::getString()
        {
            if (type == _uninitialized)
                return "";
            else if (type == _bool)
                return (b == true ? "true" : "false");
            else if (type == _int)
            {
                stringstream ss;
                ss << (int)i;
                return ss.str();
            }
            else if (type == _string)
                return s;
            else if (type == _data)
            {
                stringstream ss;
                ss << (void *)d;
                return ss.str();
            }
            else
                return "";
        }

        void *ModuleValue::getData()
        {
            if (type == _uninitialized)
                return NULL;
            else if (type == _bool)
                return new bool(b);
            else if (type == _int)
                return new int(i);
            else if (type == _string)
                return new string(s);
            else if (type == _data)
                return d;
            else
                return NULL;
        }

        ModuleSignal::ModuleSignal()
        {
            sig = -1;
        }

        ModuleSignal::ModuleSignal(int s)
        {
            sig = s;
        }

        ModuleSignal::ModuleSignal(int s, vector<ModuleValue> d)
        {
            sig = s;
            data = d;
        }

        int ModuleSignal::append(ModuleValue d)
        {
            data.push_back(d);
            return 0;
        }

        int ModuleSignal::getCode()
        {
            return sig;
        }

        int ModuleSignal::size()
        {
            return data.size();
        }

        ModuleValue ModuleSignal::getData(int idx)
        {
            if (idx < 0)
                return ModuleValue();
            else if (idx >= data.size())
                return ModuleValue();
            return data[idx];
        }

        ArchModule::ArchModule()
        {
            verbose = false;
        }

        string ArchModule::getName()
        {
            return name;
        }

        string ArchModule::setName(string n)
        {
            return (name = n);
        }

        void ArchModule::enableVerbose()
        {
            verbose = true;
        }

        int ArchModule::signal(ModuleSignal s, Architecture &a)
        {
            Z_WARNING("signalling module superclass");
            return 1;
        }

        ModuleValue ArchModule::get(string k0, string k1, Architecture &a)
        {
            Z_WARNING("getting value from module superclass");
            return ModuleValue();
        }

        ModuleValue ArchModule::get(string k, Architecture &a)
        {
            return get(k, "", a);
        }

        ModuleValue ArchModule::set(string k0, string k1, ModuleValue v, Architecture &a)
        {
            Z_WARNING("setting value in module superclass");
            return ModuleValue();
        }

        ModuleValue ArchModule::set(string k, ModuleValue v, Architecture &a)
        {
            return set(k, "", v, a);
        }

        vector<string> ArchModule::list(Architecture &a)
        {
            Z_WARNING("listing keys in module superclass");
            vector<string> rtn;
            return rtn;
        }

        int PluginModule::bindSignalCallback(PluginModule::signalCallback c)
        {
            sigc = c;
            return 0;
        }

        int PluginModule::bindGetCallback(PluginModule::getCallback c)
        {
            getc = c;
            return 0;
        }

        int PluginModule::bindSetCallback(PluginModule::setCallback c)
        {
            setc = c;
            return 0;
        }

        int PluginModule::bindListCallback(PluginModule::listCallback c)
        {
            lsc = c;
            return 0;
        }

        int PluginModule::signal(ModuleSignal s, Architecture &a)
        {
            return sigc(&s, &a);
        }

        ModuleValue PluginModule::get(string k0, string k1, Architecture &a)
        {
            return *getc((char *)k0.c_str(), (char *)k1.c_str(), &a);
        }

        ModuleValue PluginModule::set(string k0, string k1, ModuleValue v, Architecture &a)
        {
            return *setc((char *)k0.c_str(), (char *)k1.c_str(), &v, &a);
        }

        vector<string> PluginModule::list(Architecture &a)
        {
            char **tmp = lsc(&a);
            vector<string> rtn;
            for (int i = 0; tmp[i] != NULL; i++)
                rtn.push_back(string(tmp[i]));
            return rtn;
        }
    }
}
